<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">
    <meta http-equiv="X-UA-Compatible" content="ie=edge,chrome=1">
    <meta name="referrer" content="never">
    <title>对象克隆</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
        ul {
            list-style: none;
        }
    </style>
</head>
<body>
    
    <script type="text/javascript">
        /* 
        浅克隆：克隆完成后，克隆的值与原始值某个属性有关联，更改一个，另一个会跟着更改
            1. 复制对象 = 原始对象
            2. Object.assign(目标对象, 扩展对象, ...)  返回值为第一个接受的对象
                作用：将扩展对象的属性赋予 第一个接受对象，如果有重复属性，后面的会覆盖前面的
        深克隆：克隆的值与原始值没有一丝关联
            1. Object.assign({}, 原始对象)   仅限于对象属性不是引用类型
            2. JSON.parse(JSON.stringify(原始对象))  会丢失对象的方法
            3. 递归调用
        */

        var obj = {
            age: 12,
            name: "李白",
            tel: "12347812",
            friends: ["杜甫", "汪伦"],
            say(){
                console.log(this.name);
            }
        }

        // var cloneObj = obj;
        // var cloneObj = Object.assign(obj);

        // var cloneObj = Object.assign({}, obj);
        var cloneObj = JSON.parse(JSON.stringify(obj));

        cloneObj.age = 24;
        console.log("obj.age", obj.age);

        cloneObj.friends.push("判官");
        console.log("obj.friends", obj.friends);

        console.log("cloneObj.friends === obj.friends", cloneObj.friends === obj.friends);

        console.log("cloneObj === obj", cloneObj === obj);
        console.log(cloneObj);

        var deepCloneObj = deepClone(obj);
        console.log("deepCloneObj === obj", deepCloneObj === obj); // false
        console.log("deepCloneObj.friends === obj.friends", deepCloneObj.friends === obj.friends); // false
        console.log("deepCloneObj", deepCloneObj); // {... say(){}}

        console.log("deepCloneObj.say === obj.say", deepCloneObj.say === obj.say); // true
        deepCloneObj.say = function (){
            console.log("更改后的值");
        }

        deepCloneObj.say();
        obj.say();

        function deepClone(params){
            if(params === null){
                return null;
            }else if(Array.isArray(params)){
                var newObj = [];
            }else {
                var newObj = {};
            }

            for(var i in params){
                // 判断属性值是否是引用类型，如果是，深克隆值
                // 1. null   2. array   3. object
                if(typeof params[i] === "object"){
                    newObj[i] = deepClone(obj[i]);
                }else {
                    newObj[i] = params[i];
                }
            }
            return newObj;
        }

        console.clear();

        var arr = [{}, 1,2,34,5];
        // 数组的浅克隆  cloneArr = arr
        /* 深克隆：  仅适用于数组成员是非引用类型
            cloneArr = arr.slice(0)
            for 生成新的
            cloneArr = [].concat(arr)
            ...
            JSON
        */
        // var cloneArr = deepClone(arr);
        var cloneArr = arr.slice(0);

        console.log(cloneArr === arr); // false
        console.log(cloneArr[0] === arr[0]); // true
    </script>
</body>
</html>